import re
from string import lower
from myproject.auth.models import User, AbstractUser, Student, Teacher, Institute
from django.shortcuts import render_to_response
from django.template import RequestContext
from myproject.myprofile.views import getUser

'''
author: Nader
date: 18.2.12
desc: Searches for everything
params: HttpRequest
GETparams: string query
'''
def search(request):
    query = request.GET['query'] 
    category = request.GET['category']
       
    if re.match(r'^\".*\"$', query) or re.match(r'^\'.*\'$', query): # Search for exact query
        if re.match(r'^\".*\"$', query): #remove the double quotations
            query = re.sub("^\"(.*)\"$", r'''\1''', query)
        else: #remove the single quotations
            query = re.sub("^\'(.*)\'$", r'''\1''', query)
        
        # Start search
        if not lower(query).__contains__("or"): # Search for exact query, all ANDed
            [students, teachers, institutes, t_experience, s_experience,
             t_favourite_genre, s_favourite_genre, t_instrument_played,
             s_instrument_played, t_jamming_style, s_jamming_style, teaches, about, contact_info] = searchExact(query)
        else: # Search for exact query, part ORed, part ANDed
            if re.match(r'^.+\s.+\sor\s.+\s.+', query): # e.g. Nader Joseph or Saady Alexan
                first = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\1''', query)
                second = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\2''', query)
                third = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\3''', query)
                fourth = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\4''', query)
            elif re.match(r'^.+\s.+\sor\s.+$', query): # e.g. Nader Joseph or Saady
                first = re.sub(r'^(.+)\s(.+)\sor\s(.+)$', r'''\1''', query)
                second = re.sub(r'^(.+)\s(.+)\sor\s(.+)$', r'''\2''', query)
                third = re.sub(r'^(.+)\s(.+)\sor\s(.+)$', r'''\3''', query)
                fourth = ""
            elif re.match(r'^.+\sor\s.+\s.+', query):# e.g. Joseph or Saady Alexan
                first = ""
                second = re.sub(r'^(.+)\sor\s(.+)\s(.+)', r'''\1''', query)
                third = re.sub(r'^(.+)\sor\s(.+)\s(.+)', r'''\2''', query)
                fourth = re.sub(r'^(.+)\sor\s(.+)\s(.+)', r'''\3''', query)   
            else: # e.g. Joseph or Saady
                first = ""
                second = re.sub(r'^(.+)\sor\s(.+)$', r'''\1''', query)
                third = re.sub(r'^(.+)\sor\s(.+)$', r'''\2''', query)
                fourth = ""
            
            [students_1_4, teachers_1_4, institutes_1_4, t_experience_1_4, s_experience_1_4,
             t_favourite_genre_1_4, s_favourite_genre_1_4, t_instrument_played_1_4,
             s_instrument_played_1_4, t_jamming_style_1_4, s_jamming_style_1_4, 
             teaches_1_4, about_1_4, contact_info_1_4] = searchExact(first + " " + fourth)
            
            #OR the second and third
            [students_2_3, teachers_2_3, institutes_2_3, t_experience_2_3, s_experience_2_3,
             t_favourite_genre_2_3, s_favourite_genre_2_3, t_instrument_played_2_3,
             s_instrument_played_2_3, t_jamming_style_2_3, s_jamming_style_2_3, 
             teaches_2_3, about_2_3, contact_info_2_3] = searchORexact(second, third)
             
            [students, teachers, institutes, t_experience, s_experience,
              t_favourite_genre, s_favourite_genre, t_instrument_played,
              s_instrument_played, t_jamming_style, s_jamming_style, 
              teaches, about, contact_info] = [(students_1_4 & students_2_3) | (students_2_3 & students_1_4),
                                             (teachers_1_4 & teachers_2_3) | (teachers_2_3 & teachers_1_4),
                                             (institutes_1_4 & institutes_2_3) | (institutes_2_3 & institutes_1_4),
                                             (t_experience_1_4 & t_experience_2_3) | (t_experience_2_3 & t_experience_1_4),
                                             (s_experience_1_4 & s_experience_2_3) | (s_experience_2_3 & s_experience_1_4),
                                             (t_favourite_genre_1_4 & t_favourite_genre_2_3) | (t_favourite_genre_2_3 & t_favourite_genre_1_4),
                                             (s_favourite_genre_1_4 & s_favourite_genre_2_3) | (s_favourite_genre_2_3 & s_favourite_genre_1_4),
                                             (t_instrument_played_1_4 & t_instrument_played_2_3) | (t_instrument_played_2_3 & t_instrument_played_1_4),
                                             (s_instrument_played_1_4 & s_instrument_played_2_3) | (s_instrument_played_2_3 & s_instrument_played_1_4),
                                             (t_jamming_style_1_4 & t_jamming_style_2_3) | (t_jamming_style_2_3 & t_jamming_style_1_4),
                                             (s_jamming_style_1_4 & s_jamming_style_2_3) | (s_jamming_style_2_3 & s_jamming_style_1_4),
                                             (teaches_1_4 & teaches_2_3) | (teaches_2_3 & teaches_1_4),
                                             (about_1_4 & about_2_3) | (about_2_3 & about_1_4),
                                             (contact_info_1_4 & contact_info_2_3) | (contact_info_2_3 & contact_info_1_4)]
        
    else: # Search for icontains query
        query = removeStopWords(lower(query))
        if not query.__contains__("or"): # Search for icontains query, at least two words matching query if query is more than two words. If query is two words, or them.
            # Get search results for icontains arguments
            [students, teachers, institutes, t_experience, s_experience,
             t_favourite_genre, s_favourite_genre, t_instrument_played,
             s_instrument_played, t_jamming_style, s_jamming_style, teaches, about, contact_info] = searchTwoWordIContains(query)
        else: # Search for icontains query, part ANDed, part ORed
            if re.match(r'^.+\s.+\sor\s.+\s.+', query): # e.g. Nader Joseph or Saady Alexan
                first = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\1''', query)
                second = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\2''', query)
                third = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\3''', query)
                fourth = re.sub(r'^(.+)\s(.+)\sor\s(.+)\s(.+)', r'''\4''', query)
            elif re.match(r'^.+\s.+\sor\s.+$', query): # e.g. Nader Joseph or Saady
                first = re.sub(r'^(.+)\s(.+)\sor\s(.+)$', r'''\1''', query)
                second = re.sub(r'^(.+)\s(.+)\sor\s(.+)$', r'''\2''', query)
                third = re.sub(r'^(.+)\s(.+)\sor\s(.+)$', r'''\3''', query)
                fourth = ""
            elif re.match(r'^.+\sor\s.+\s.+', query):# e.g. Joseph or Saady Alexan
                first = ""
                second = re.sub(r'^(.+)\sor\s(.+)\s(.+)', r'''\1''', query)
                third = re.sub(r'^(.+)\sor\s(.+)\s(.+)', r'''\2''', query)
                fourth = re.sub(r'^(.+)\sor\s(.+)\s(.+)', r'''\3''', query)   
            else: # e.g. Joseph or Saady
                first = ""
                second = re.sub(r'^(.+)\sor\s(.+)$', r'''\1''', query)
                third = re.sub(r'^(.+)\sor\s(.+)$', r'''\2''', query)
                fourth = ""
                
            [students_1_4, teachers_1_4, institutes_1_4, t_experience_1_4, s_experience_1_4,
             t_favourite_genre_1_4, s_favourite_genre_1_4, t_instrument_played_1_4,
             s_instrument_played_1_4, t_jamming_style_1_4, s_jamming_style_1_4, 
             teaches_1_4, about_1_4, contact_info_1_4] = searchIContains(first + " " + fourth)
            
            #OR the second and third
            [students_2_3, teachers_2_3, institutes_2_3, t_experience_2_3, s_experience_2_3,
             t_favourite_genre_2_3, s_favourite_genre_2_3, t_instrument_played_2_3,
             s_instrument_played_2_3, t_jamming_style_2_3, s_jamming_style_2_3, 
             teaches_2_3, about_2_3, contact_info_2_3] = searchORicontains(second, third)
             
            [students, teachers, institutes, t_experience, s_experience,
              t_favourite_genre, s_favourite_genre, t_instrument_played,
              s_instrument_played, t_jamming_style, s_jamming_style, 
              teaches, about, contact_info] = [(students_1_4 & students_2_3) | (students_2_3 & students_1_4),
                                             (teachers_1_4 & teachers_2_3) | (teachers_2_3 & teachers_1_4),
                                             (institutes_1_4 & institutes_2_3) | (institutes_2_3 & institutes_1_4),
                                             (t_experience_1_4 & t_experience_2_3) | (t_experience_2_3 & t_experience_1_4),
                                             (s_experience_1_4 & s_experience_2_3) | (s_experience_2_3 & s_experience_1_4),
                                             (t_favourite_genre_1_4 & t_favourite_genre_2_3) | (t_favourite_genre_2_3 & t_favourite_genre_1_4),
                                             (s_favourite_genre_1_4 & s_favourite_genre_2_3) | (s_favourite_genre_2_3 & s_favourite_genre_1_4),
                                             (t_instrument_played_1_4 & t_instrument_played_2_3) | (t_instrument_played_2_3 & t_instrument_played_1_4),
                                             (s_instrument_played_1_4 & s_instrument_played_2_3) | (s_instrument_played_2_3 & s_instrument_played_1_4),
                                             (t_jamming_style_1_4 & t_jamming_style_2_3) | (t_jamming_style_2_3 & t_jamming_style_1_4),
                                             (s_jamming_style_1_4 & s_jamming_style_2_3) | (s_jamming_style_2_3 & s_jamming_style_1_4),
                                             (teaches_1_4 & teaches_2_3) | (teaches_2_3 & teaches_1_4),
                                             (about_1_4 & about_2_3) | (about_2_3 & about_1_4),
                                             (contact_info_1_4 & contact_info_2_3) | (contact_info_2_3 & contact_info_1_4)]

    loggedIn = request.user.is_authenticated()
    
    empty = True
    if category == 'all':
        if students or teachers or institutes or t_experience or s_experience or t_favourite_genre or s_favourite_genre or t_instrument_played or s_instrument_played or t_jamming_style or s_jamming_style or teaches or about or contact_info:
            empty = False
    elif category == 'students': 
        if students: empty = False
    elif category == 'teachers':
        if teachers: empty = False
    elif category == 'institutes':
        if institutes: empty = False
    elif category == 'experience':
        if t_experience or s_experience: empty = False
    elif category == 'favourite_genre':
        if t_favourite_genre or s_favourite_genre: empty = False
    elif category == 'instrument_played':
        if t_instrument_played or s_instrument_played: empty = False
    elif category == 'jamming_style':
        if t_jamming_style or s_jamming_style: empty = False
    elif category == 'teaches':
        if teaches: empty = False
    else:
        print category

    loggedInUser = currentUser = getUser(request.user, abstract=False)
    profileOwner = True
    
    return render_to_response('searchresults.html', {'loggedInUser':loggedInUser, 'currentUser':currentUser, 'profileOwner':profileOwner,
                                                     'category':category, 'students':students, 'teachers':teachers, 'institutes':institutes,
                                                     't_experience':t_experience, 's_experience':s_experience,
                                                     't_favourite_genre':t_favourite_genre, 's_favourite_genre':s_favourite_genre,
                                                     't_instrument_played':t_instrument_played, 's_instrument_played':s_instrument_played,
                                                     't_jamming_style':t_jamming_style, 's_jamming_style':s_jamming_style,
                                                     'teaches':teaches, 'about':about, 'contact_info':contact_info, 'query':query, 'loggedIn':loggedIn, 'empty':empty}, context_instance=RequestContext(request))
    
def searchExact(query):
    if query == " " or not query or query == '':
        return [Student.objects.all(), Teacher.objects.all(), Institute.objects.all(),
                Teacher.objects.all(), Student.objects.all(), Teacher.objects.all(),
                Student.objects.all(), Teacher.objects.all(), Student.objects.all(),
                Teacher.objects.all(), Student.objects.all(), Teacher.objects.all()]
    
    #Initially all objects are considered results, until we narrow down
    users = User.objects.all()
    #abstract_user = AbstractUser.objects.all()
    #students, teachers, institutes = Student.objects.all(), Teacher.objects.all(), Institute.objects.all()
    t_experience, s_experience = Teacher.objects.all(), Student.objects.all() 
    t_favourite_genre, s_favourite_genre = Teacher.objects.all(), Student.objects.all() 
    t_instrument_played, s_instrument_played = Teacher.objects.all(), Student.objects.all()
    t_jamming_style, s_jamming_style = Teacher.objects.all(), Student.objects.all()
    teaches = Teacher.objects.all()
    about, contact_info = Institute.objects.all(), Institute.objects.all()
    
    queryArr = query.split(" ") #Split words in the query    
    for ele in queryArr:#Loop through the elements and AND them
        if ele == "":
            continue
        '''
        USERS
        '''
        #USER attributes searched
        users &= (User.objects.filter(username__exact=ele) | User.objects.filter(email__exact=ele) | User.objects.filter(first_name__exact=ele) | User.objects.filter(last_name__exact=ele))
        
        '''
        USER ATTRIBUTE
        '''
        #Experience
        t_experience &= Teacher.objects.filter(experience__exact=ele)
        s_experience &= Student.objects.filter(experience__exact=ele)
        #Favourite_genre
        t_favourite_genre &= Teacher.objects.filter(favourite_genre__exact=ele)
        s_favourite_genre &= Student.objects.filter(favourite_genre__exact=ele)
        #Instrument_played
        t_instrument_played &= Teacher.objects.filter(instrument_played__exact=ele)
        s_instrument_played &= Student.objects.filter(instrument_played__exact=ele)
        #Jamming_style
        t_jamming_style &= Teacher.objects.filter(jamming_style__exact=ele)
        s_jamming_style &= Student.objects.filter(jamming_style__exact=ele)
        #Teaches
        teaches &= Teacher.objects.filter(teaches__exact=ele)
        #About
        about &= Institute.objects.filter(about__exact=ele)    
        #Contact info
        contact_info &= Institute.objects.filter(contact_info__exact=ele)

    
    abstract_user, students, teachers, institutes = divUsers(users)
    
    return [students, teachers, institutes, t_experience, s_experience,
            t_favourite_genre, s_favourite_genre, t_instrument_played,
            s_instrument_played, t_jamming_style, s_jamming_style, teaches,
            about, contact_info]

def searchIContains(query):
    
    if query == " " or not query or query == '':
        return [Student.objects.all(), Teacher.objects.all(), Institute.objects.all(),
                Teacher.objects.all(), Student.objects.all(), Teacher.objects.all(),
                Student.objects.all(), Teacher.objects.all(), Student.objects.all(),
                Teacher.objects.all(), Student.objects.all(), Teacher.objects.all()]
    #Initially all objects are considered results, until we narrow down
    users = User.objects.all()
    #abstract_user = AbstractUser.objects.all()
    #students, teachers, institutes = Student.objects.all(), Teacher.objects.all(), Institute.objects.all()
    t_experience, s_experience = Teacher.objects.all(), Student.objects.all() 
    t_favourite_genre, s_favourite_genre = Teacher.objects.all(), Student.objects.all() 
    t_instrument_played, s_instrument_played = Teacher.objects.all(), Student.objects.all()
    t_jamming_style, s_jamming_style = Teacher.objects.all(), Student.objects.all()
    teaches = Teacher.objects.all()
    about, contact_info = Institute.objects.all(), Institute.objects.all()
    
    queryArr = query.split(" ") #Split words in the query
  
    for ele in queryArr:#Loop through the elements and AND them
        if ele == "":
            continue
        '''
        USERS
        '''
        #USER attributes searched
        users &= (User.objects.filter(username__icontains=ele) | \
                  User.objects.filter(email__icontains=ele) | \
                   User.objects.filter(first_name__icontains=ele) | \
                   User.objects.filter(last_name__icontains=ele))
        

        '''
        USER ATTRIBUTE
        '''
        #Experience
        t_experience &= Teacher.objects.filter(experience__icontains=ele)
        s_experience &= Student.objects.filter(experience__icontains=ele)
        #Favourite_genre
        t_favourite_genre &= Teacher.objects.filter(favourite_genre__icontains=ele)
        s_favourite_genre &= Student.objects.filter(favourite_genre__icontains=ele)
        #Instrument_played
        t_instrument_played &= Teacher.objects.filter(instrument_played__icontains=ele)
        s_instrument_played &= Student.objects.filter(instrument_played__icontains=ele)
        #Jamming_style
        t_jamming_style &= Teacher.objects.filter(jamming_style__icontains=ele)
        s_jamming_style &= Student.objects.filter(jamming_style__icontains=ele)
        #Teaches
        teaches &= Teacher.objects.filter(teaches__icontains=ele)
        #About
        about &= Institute.objects.filter(about__icontains=ele)    
        #Contact info
        contact_info &= Institute.objects.filter(contact_info__icontains=ele)

    
    abstract_user, students, teachers, institutes = divUsers(users)
    
    return [students, teachers, institutes, t_experience, s_experience,
            t_favourite_genre, s_favourite_genre, t_instrument_played,
            s_instrument_played, t_jamming_style, s_jamming_style, teaches,
            about, contact_info]

def searchORicontains(query1, query2):
    '''
    USERS
    '''
    #USER attributes searched
    users = User.objects.filter(username__icontains=query1) | User.objects.filter(email__icontains=query1) | \
             User.objects.filter(first_name__icontains=query1) | User.objects.filter(last_name__icontains=query1) | \
             User.objects.filter(username__icontains=query2) | User.objects.filter(email__icontains=query2) | \
             User.objects.filter(first_name__icontains=query2) | User.objects.filter(last_name__icontains=query2)
    
    abstract_user, students, teachers, institutes = divUsers(users)

    '''
    USER ATTRIBUTE
    '''
    #Experience
    t_experience = Teacher.objects.filter(experience__icontains=query1) | Teacher.objects.filter(experience__icontains=query2)
    s_experience = Student.objects.filter(experience__icontains=query1) | Student.objects.filter(experience__icontains=query2) 
    #Favourite_genre
    t_favourite_genre = Teacher.objects.filter(favourite_genre__icontains=query1) | Teacher.objects.filter(favourite_genre__icontains=query2)
    s_favourite_genre = Student.objects.filter(favourite_genre__icontains=query1) | Student.objects.filter(favourite_genre__icontains=query2)
    #Instrument_played
    t_instrument_played = Teacher.objects.filter(instrument_played__icontains=query1) | Teacher.objects.filter(instrument_played__icontains=query2)
    s_instrument_played = Student.objects.filter(instrument_played__icontains=query1) | Student.objects.filter(instrument_played__icontains=query2)
    #Jamming_style
    t_jamming_style = Teacher.objects.filter(jamming_style__icontains=query1) | Teacher.objects.filter(jamming_style__icontains=query2)
    s_jamming_style = Student.objects.filter(jamming_style__icontains=query1) | Student.objects.filter(jamming_style__icontains=query2)
    #Teaches
    teaches = Teacher.objects.filter(teaches__icontains=query1) | Teacher.objects.filter(teaches__icontains=query2)
    #About
    about = Institute.objects.filter(about__icontains=query1) | Institute.objects.filter(about__icontains=query2)  
    #Contact info 
    contact_info = Institute.objects.filter(contact_info__icontains=query1) | Institute.objects.filter(contact_info__icontains=query2)

    return [students, teachers, institutes, t_experience, s_experience,
            t_favourite_genre, s_favourite_genre, t_instrument_played,
            s_instrument_played, t_jamming_style, s_jamming_style, teaches,
            about, contact_info]

def searchORexact(query1, query2):
    '''
    USERS
    '''
    #USER attributes searched
    users = User.objects.filter(username__exact=query1) | User.objects.filter(email__exact=query1) | \
             User.objects.filter(first_name__exact=query1) | User.objects.filter(last_name__exact=query1) | \
             User.objects.filter(username__exact=query2) | User.objects.filter(email__exact=query2) | \
             User.objects.filter(first_name__exact=query2) | User.objects.filter(last_name__exact=query2)
    
    abstract_user, students, teachers, institutes = divUsers(users)
    
    '''
    USER ATTRIBUTE
    '''
    #Experience
    t_experience = Teacher.objects.filter(experience__exact=query1) | Teacher.objects.filter(experience__exact=query2)
    s_experience = Student.objects.filter(experience__exact=query1) | Student.objects.filter(experience__exact=query2) 
    #Favourite_genre
    t_favourite_genre = Teacher.objects.filter(favourite_genre__exact=query1) | Teacher.objects.filter(favourite_genre__exact=query2)
    s_favourite_genre = Student.objects.filter(favourite_genre__exact=query1) | Student.objects.filter(favourite_genre__exact=query2)
    #Instrument_played
    t_instrument_played = Teacher.objects.filter(instrument_played__exact=query1) | Teacher.objects.filter(instrument_played__exact=query2)
    s_instrument_played = Student.objects.filter(instrument_played__exact=query1) | Student.objects.filter(instrument_played__exact=query2)
    #Jamming_style
    t_jamming_style = Teacher.objects.filter(jamming_style__exact=query1) | Teacher.objects.filter(jamming_style__exact=query2)
    s_jamming_style = Student.objects.filter(jamming_style__exact=query1) | Student.objects.filter(jamming_style__exact=query2)
    #Teaches
    teaches = Teacher.objects.filter(teaches__exact=query1) | Teacher.objects.filter(teaches__exact=query2)
    #About
    about = Institute.objects.filter(about__exact=query1) | Institute.objects.filter(about__exact=query2)  
    #Contact info 
    contact_info = Institute.objects.filter(contact_info__exact=query1) | Institute.objects.filter(contact_info__exact=query2)

    return [students, teachers, institutes, t_experience, s_experience,
            t_favourite_genre, s_favourite_genre, t_instrument_played,
            s_instrument_played, t_jamming_style, s_jamming_style, teaches,
            about, contact_info]

def divUsers(users):
    abstract_user = None
    for u in users:
      if abstract_user:
        abstract_user |= AbstractUser.objects.filter(user=u)
      else:
          abstract_user = AbstractUser.objects.filter(user=u)

    # initiate the arrays
    students, teachers, institutes = Student.objects.filter(pk=-1), Teacher.objects.filter(pk=-1), Institute.objects.filter(pk=-1)

    if abstract_user:
        for au in abstract_user:
            #Get Students
            if students:
              students |= Student.objects.filter(abstract_user=au)
            else:
              students = Student.objects.filter(abstract_user=au)
            #Get Teachers
            if teachers:
              teachers |= Teacher.objects.filter(abstract_user=au)
            else:
              teachers = Teacher.objects.filter(abstract_user=au)
            #Get Institutes
            if institutes:
              institutes |= Institute.objects.filter(abstract_user=au)
            else:
              institutes = Institute.objects.filter(abstract_user=au)
    return abstract_user, students, teachers, institutes


'''
author:Nader
date: 10.04.12
desc: Given a query of n words, if nreturn users matching atleast 2 words. 
'''
def searchTwoWordIContains(query):
    query = query.strip()
    query = ' '.join(query.split())
    if query == " " or not query or query == '':
        print 1
        return [Student.objects.all(), Teacher.objects.all(), Institute.objects.all(),
                Teacher.objects.all(), Student.objects.all(), Teacher.objects.all(),
                Student.objects.all(), Teacher.objects.all(), Student.objects.all(),
                Teacher.objects.all(), Student.objects.all(), Teacher.objects.all(),
                Institute.objects.all(), Institute.objects.all()]
    elif len(query.split(' ')) == 1:
        print 2
        return searchIContains(query.strip())
    elif re.match(r'^\s*[a-zA-Z]+\s+[a-zA-Z]+\s*$', query):
        print 3
        print "inCorrect GIL"
        return searchORicontains(query.split(' ')[0], query.split(' ')[1])

    #have a list of words from the query
    words = query.split(" ")

    #have a list of intermediate results
    results = []
    for ele in words:
        if ele == "":
              continue
        #Initially all objects are considered results, until we narrow down
        users = User.objects.all()
        #abstract_user = AbstractUser.objects.all()
        #students, teachers, institutes = Student.objects.all(), Teacher.objects.all(), Institute.objects.all()
        t_experience, s_experience = Teacher.objects.all(), Student.objects.all() 
        t_favourite_genre, s_favourite_genre = Teacher.objects.all(), Student.objects.all() 
        t_instrument_played, s_instrument_played = Teacher.objects.all(), Student.objects.all()
        t_jamming_style, s_jamming_style = Teacher.objects.all(), Student.objects.all()
        teaches = Teacher.objects.all()
        about, contact_info = Institute.objects.all(), Institute.objects.all()
      
      
        '''
        USERS
        '''
        #USER attributes searched
        users &= (User.objects.filter(username__icontains=ele) | \
                  User.objects.filter(email__icontains=ele) | \
                   User.objects.filter(first_name__icontains=ele) | \
                   User.objects.filter(last_name__icontains=ele))
        
        '''
        USER ATTRIBUTE
        '''
        #Experience
        t_experience &= Teacher.objects.filter(experience__icontains=ele)
        s_experience &= Student.objects.filter(experience__icontains=ele)
        #Favourite_genre
        t_favourite_genre &= Teacher.objects.filter(favourite_genre__icontains=ele)
        s_favourite_genre &= Student.objects.filter(favourite_genre__icontains=ele)
        #Instrument_played
        t_instrument_played &= Teacher.objects.filter(instrument_played__icontains=ele)
        s_instrument_played &= Student.objects.filter(instrument_played__icontains=ele)
        #Jamming_style
        t_jamming_style &= Teacher.objects.filter(jamming_style__icontains=ele)
        s_jamming_style &= Student.objects.filter(jamming_style__icontains=ele)
        #Teaches
        teaches &= Teacher.objects.filter(teaches__icontains=ele)
        #About
        about &= Institute.objects.filter(about__icontains=ele)    
        #Contact info
        contact_info &= Institute.objects.filter(contact_info__icontains=ele)
        
        results.append([users, t_experience, s_experience,
          t_favourite_genre, s_favourite_genre, t_instrument_played,
          s_instrument_played, t_jamming_style, s_jamming_style, teaches, about, contact_info]) 
    results_combined = None
    for out_index in range(len(results)):
        [out_users, out_t_experience, out_s_experience, out_t_favourite_genre, out_s_favourite_genre, out_t_instrument_played, out_s_instrument_played, out_t_jamming_style, out_s_jamming_style, out_teaches, out_about, out_contact_info] = results[out_index]
        for in_index in range(out_index+1, len(results)):
            [in_users, in_t_experience, in_s_experience, in_t_favourite_genre, in_s_favourite_genre, in_t_instrument_played, in_s_instrument_played, in_t_jamming_style, in_s_jamming_style, in_teaches, in_about, in_contact_info] = results[in_index]
            if results_combined:
                [users, t_experience, s_experience,
                t_favourite_genre, s_favourite_genre, t_instrument_played,
                s_instrument_played, t_jamming_style, s_jamming_style, teaches, about, contact_info] = results_combined
                results_combined = [users | (out_users & in_users) | (in_users & out_users), 
                                    t_experience | (out_t_experience & in_t_experience) | (in_t_experience & out_t_experience), 
                                    s_experience | (out_s_experience & in_s_experience) | (in_s_experience & out_s_experience), 
                                    t_favourite_genre | (out_t_favourite_genre & in_t_favourite_genre) | (in_t_favourite_genre & out_t_favourite_genre), 
                                    s_favourite_genre | (out_s_favourite_genre & in_s_favourite_genre) | (in_s_favourite_genre & out_s_favourite_genre), 
                                    t_instrument_played | (out_t_instrument_played & in_t_instrument_played) | (in_t_instrument_played & out_t_instrument_played), 
                                    s_instrument_played | (out_s_instrument_played & in_s_instrument_played) | (in_s_instrument_played & out_s_instrument_played), 
                                    t_jamming_style | (out_t_jamming_style & in_t_jamming_style) | (in_t_jamming_style & out_t_jamming_style), 
                                    s_jamming_style | (out_s_jamming_style & in_s_jamming_style) | (in_s_jamming_style & out_s_jamming_style), 
                                    teaches | (out_teaches & in_teaches) | (in_teaches & out_teaches), 
                                    about | (out_about & in_about) | (in_about & out_about), 
                                    contact_info | (out_contact_info & in_contact_info) | (in_contact_info & out_contact_info)]

            else:
                results_combined = [(out_users & in_users) | (in_users & out_users), 
                                    (out_t_experience & in_t_experience) | (in_t_experience & out_t_experience), 
                                    (out_s_experience & in_s_experience) | (in_s_experience & out_s_experience), 
                                    (out_t_favourite_genre & in_t_favourite_genre) | (in_t_favourite_genre & out_t_favourite_genre), 
                                    (out_s_favourite_genre & in_s_favourite_genre) | (in_s_favourite_genre & out_s_favourite_genre), 
                                    (out_t_instrument_played & in_t_instrument_played) | (in_t_instrument_played & out_t_instrument_played), 
                                    (out_s_instrument_played & in_s_instrument_played) | (in_s_instrument_played & out_s_instrument_played), 
                                    (out_t_jamming_style & in_t_jamming_style) | (in_t_jamming_style & out_t_jamming_style), 
                                    (out_s_jamming_style & in_s_jamming_style) | (in_s_jamming_style & out_s_jamming_style), 
                                    (out_teaches & in_teaches) | (in_teaches & out_teaches), 
                                    (out_about & in_about) | (in_about & out_about), 
                                    (out_contact_info & in_contact_info) | (in_contact_info & out_contact_info)]
                
    [users, t_experience, s_experience,
    t_favourite_genre, s_favourite_genre, t_instrument_played,
    s_instrument_played, t_jamming_style, s_jamming_style, teaches, about, contact_info] = results_combined

    abstract_user, students, teachers, institutes = divUsers(users)

    return [students, teachers, institutes, t_experience, s_experience,
            t_favourite_genre, s_favourite_genre, t_instrument_played,
            s_instrument_played, t_jamming_style, s_jamming_style, teaches, about, contact_info]


def removeStopWords(query):
    stop_words = ['a','adj','ago','ain\'t','all','am','an','and','any','are','aren\'t','as','a\'s','ask','at',
                'b','be','but','by','c','can','can\'t','c\'mon','co','co.','com','couldn\'t','c\'s','d','did','didn\'t',
                'do','doesn\'t','don\'t','e','edu','eg','end','et','etc','ex','f','far','few','for','g','get','go','got',
                'h','had','hadn\'t','has','hasn\'t','haven\'t','he','he\'d','he\'ll','her','here\'s','he\'s','hi','him',
                'his','how','i','i\'d','ie','if','i\'ll','i\'m','in','inc','inc.','is','isn\'t','it','its','it\'s','i\'ve',
                'j','k','l','let','low','ltd','m','may','me','mr','mrs','my','n','nd','new','no','non','no-one','nor','not',
                'now','o','of','off','oh','ok','old','on','one','or','our','out','own','p','per','q','que','qv','r','rd','re',
                's','saw','say','see','she','six','so','sub','sup','t','th','the','to','too','try','two','u','un','up','us',
                'use','v','via','viz','vs','w','was','way','we','who','why','x','y','yes','yet','you','z','zero']
    for word in stop_words:
        query = query.replace(' ' + word + ' ',' ')
    return query